import { IconDefine, LightType, ObjInfo } from "./IconDefine";

export class IconView {

    public onObjCreated: Function;
    private objs: mw.GameObject[] = [];
    private isCreating: boolean = false;
    private waitId: any;
    private deltaPos: mw.Vector = new mw.Vector(0, 0, 0);
    private viewBase: mweditor.ViewBase;
    private floorObj: mw.GameObject;
    private lightObj: mw.Lighting;
    private objMap: Map<string, ObjInfo> = new Map();
    public async init(view: mweditor.ViewBase) {
        this.viewBase = view;
        view.worldTransform.position = new mw.Vector(0, 600, 300);
        view.worldTransform.rotation = new mw.Rotation(0, -14, -90);
        await view.asyncSpawnInViewport("SkyBox", {});
        this.lightObj = await view.asyncSpawnInViewport("Lighting", {}) as mw.Lighting;
        this.floorObj = await view.asyncSpawnInViewport("162053", {});
        this.floorObj.worldTransform.position = new mw.Vector(0, 0, 0);

        let outl = mweditor.findEditorSystem(mweditor.Outliner)
        outl.clearSelectionSet();
        outl.onSelectionGameObjectsEvent.add(this.onObjSelected);
        // outl.onClearSelectionGameObjectsEvent.add(() => {
        //     console.log('ts3 onClearSelectionGameObjectsEvent');
        // });
    }
    public onDestroy() {
        let outl = mweditor.findEditorSystem(mweditor.Outliner)
        outl.onSelectionGameObjectsEvent.remove(this.onObjSelected);
        this.viewBase = null;
    }
    private onObjSelected = (objs: GameObject[]) => {
        if (this.isCreating || IconDefine.isIgnoreObj(objs[0])) {
            return;
        }
        this.waitId && clearTimeout(this.waitId);
        this.waitId = setTimeout(() => {
            let obj = objs[0];
            let cp = obj.worldTransform.position;
            IconDefine.photoName = obj.name;
            this.deltaPos.x = -cp.x;
            this.deltaPos.y = -cp.y;
            this.deltaPos.z = - cp.z;
            this.createObjs(objs);
            this.waitId = null;
        }, 1000);
    }
    private async getObjsByFile() {
        let path = mweditor.File.curProjectPath + "/Levels/NewLevel.level";
        let file = mweditor.File.open(path)
        if (!file)
            return;
        let txt = await file.read();
        let json = JSON.parse(txt);
        let data = json['Scene'];
        if (!data)
            return;
        for (let obj of data) {
            let guid = obj['Guid'];
            let asset = obj['Asset'];
            //世界对象不加入搜索
            if (IconDefine.ignores.indexOf(asset) >= 0)
                continue;
            if (!guid)
                continue;
            let mats = obj['StaticMesh'] ? obj['StaticMesh']['Materials'] : null;
            let list = [];
            if (mats) {
                for (let k in mats) {
                    list.push(mats[k])
                }
            }
            let maskColor;
            let efColor = [];
            if (obj['Effects']) {
                maskColor = this.getColor(obj['MaskColor'])
                let efl = obj['InstanceParamters'];
                for (let v of efl) {
                    let color = this.getColor(v['ParticleColor']);
                    let name = v['ParticleParamName'];
                    if (!color || (color.r == 0 && color.g == 0 && color.b == 0 && color.a == 0))
                        continue;
                    let idx = IconDefine.efColorNames.indexOf(name);
                    if (idx < 0)
                        continue;
                    efColor[idx] = color;
                }
            }
            let info: ObjInfo =
            {
                guid: guid,
                assetId: asset ? asset.toLowerCase() : "",
                mats: list,
                maskColor: maskColor,
                efColor: efColor
            }
            this.objMap.set(guid, info);
        }
    }
    getColor(cfg) {
        if (!cfg)
            return null;
        let color = new mw.LinearColor(0, 0, 0, 0);
        if (cfg['R'])
            color.r = cfg['R'] / 255;
        if (cfg['G'])
            color.g = cfg['G'] / 255;
        if (cfg['B'])
            color.b = cfg['B'] / 255;
        if (cfg['A'])
            color.a = cfg['A'] / 255;
        return color;
    }
    private async createObjs(list: GameObject[]) {
        //暂时代替方案，读取文件信息，获取材质和特效颜色
        await this.getObjsByFile();
        this.isCreating = true;
        for (let obj of this.objs) {
            obj?.destroy();
        }
        this.objs = [];
        for (let o of list) {
            if (!o?.assetId)
                continue;
            await this.createObj(o);
        }

        this.onObjCreated && this.onObjCreated();
        this.isCreating = false;
        await TimeUtil.delaySecond(0.1);
        this.viewBase.focusObjects(this.objs);
    }
    // private log(obj) {
    //     for (let k in obj) {
    //         let v = obj[k];
    //         if (v instanceof Object)
    //             this.log(v);
    //         else
    //             console.log('ts3', k, v);
    //     }
    // }
    private async createObj(o: GameObject) {
        if (IconDefine.isIgnoreObj(o))
            return;
        let obj = await this.viewBase.asyncSpawnInViewport(o.assetId, {}) as mw.GameObject;
        let pos = o.worldTransform.position.add(this.deltaPos);
        let size = o.worldTransform.scale;
        //角色的位置调整，获取不到一个合适的参数，暂时这样处理
        if (obj instanceof mw.Character) {
            let char = obj as mw.Character;
            // let target = o as mw.Character;
            // let pos1 = target.getSlotWorldPosition(HumanoidSlotType.Buttocks)
            // let pos2 = target.getSlotWorldPosition(HumanoidSlotType.Root)
            let vec = char.getBoundingBoxExtent();
            // let hei = char.description.advance.bodyFeatures.body.height
            pos.z += vec.z * size.z * 0.5;
        }

        let info = this.objMap.get(o.gameObjectId)
        if (info?.mats.length > 0) {
            let model = obj as Model;
            for (let i = 0; i < info.mats.length; i++) {
                model.setMaterial(info.mats[i], i);
            }
        }
        if (info?.maskColor) {
            let ef = obj as mw.Effect;
            if (ef)
                ef.maskcolor = info.maskColor;
        }
        if (info?.efColor?.length > 0) {
            let ef = obj as mw.Effect;
            if (ef) {
                for (let i = 0; i < info.efColor.length; i++) {
                    let color = info.efColor[i];
                    if (!color)
                        continue;
                    let key = IconDefine.efColorNames[i];
                    ef.setColor(key, color);
                }
            }
            // pos.z -= 10;  //特效显示有个图标，让地面遮住图标
        }
        obj.worldTransform.position = pos;
        obj.worldTransform.rotation = o.worldTransform.rotation;
        obj.worldTransform.scale = size;
        this.objs.push(obj);
        let childs = o.getChildren();
        for (let c of childs) {
            await this.createObj(c);
        }
    }
    public showFloor(show: boolean) {
        this.floorObj.setVisibility(show);
    }
    public castShadow(cast: boolean) {
        this.lightObj['directionalLightCastShadowsEnable'] = cast;
        this.objs.forEach(obj => {
            let model = obj as Model;
            if (model)
                model.castShadow = cast;
        });
    }
    public barChanged(type: LightType, value: number) {
        if (type == LightType.Strength) {
            this.lightObj['directionalLightIntensity'] = value;
        }
        else if (type == LightType.Direction) {
            this.lightObj['directionalLightYawAngle'] = value;
        }
        else if (type == LightType.Pitch) {
            this.lightObj['directionalLightPitchAngle'] = value;
        }
    }
    public async takePhoto(): Promise<number> {
        if (this.objs.length < 1)
            return 1;
        let suc = await this.viewBase.targetObjectsScreenshotToPath(this.objs, IconDefine.savePath, IconDefine.photoName, IconDefine.photoSize);
        return suc ? 0 : 2;
    }

}

